package demo2接口使用案例;
//深拷贝
//将对象中的对象进行克隆
class Money1 implements Cloneable{
    public double money = 19.9;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person2 implements Cloneable{
    public int age;
    public Money1 m;

    public Person2(int age) {
        this.age = age;
        this.m = new Money1();//在构造方法中实例化一个money
    }

    @Override
    public String toString() {
        return "Person{" +
                " age=" + age +
                " }";
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person2 tmp = (Person2) super.clone();
        //tmp.m类的调用成员变量，this.m.clone()中的this是指这个对象的成员变量m的引用
        tmp.m = (Money1) this.m.clone();//谁调用某个方法谁就是this，现在是person1来调用，那么person1就是this
        return tmp;
    }
}
public class Test5 {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person2 person1 = new Person2(10);
        Person2 person2 = (Person2) person1.clone();
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
        System.out.println("===============");
        person2.m.money = 99.9;
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
        //这个时候person2修改完的是99.9
        /*
        在虚拟机栈上，会创建两个空间分别是person1和person2，还有一个在person类中创建一个临时变量tmp，
        因为是把对象的对象进行克隆，所以要再类中的另一个类（该类作为成员变量）中重写clone方法，但是在原有的类中的clone方法也需要进行修改
        person1所实例化的对象会在堆上创建一个对象的空间（地址为0x98），存入两个成员变量，但是其中m是Money类型即是引用类型，
        并且也是实例化了，所以那么也会是创建money类型的对象的空间（地址为0x65），这时候在对中的成员变量m也会得到它实例化的地址
        因为我们还在Person类中修改了重写方法；通过创建了一个临时变量tmp也是为Person类型，先把外面的对象先进行克隆完成，
        这时候再通过这个临时变量去调用Person类中的m(其实也就是类的引用),
        由于我将m这个变量也进行了Money类的实例化的操作，所以这时候再用m去调用正常的clone方法，从而去调用Money类中的clone方法
        这个完成了克隆那么Money类的克隆的地址（0x888)，但是tmp是临时的局部的变量，出了作用域就销毁，最终返回的是给的是person2
        [person2 = (Person2) person1.clone()]这个就是返回了person2么
        因为它是类类型（引用类型）所以这个时候的person2就会得到它的地址（0x91）
        最终person2和person1所指的两个值是不一样

        此时这个现象被称之深拷贝：完全将对象中的对象去进行克隆
         */
    }

    //深拷贝与浅拷贝就是看的是代码实现的过程，跟克隆方法没有关系
}
